home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / bind493a.zip / named / ns_forw.c < prev    next >
C/C++ Source or Header  |  1995-12-22  |  28KB  |  993 lines

  1. #if !defined(lint) && !defined(SABER)
  2. static char sccsid[] = "@(#)ns_forw.c    4.32 (Berkeley) 3/3/91";
  3. static char rcsid[] = "$Id: ns_forw.c,v 8.9 1995/12/22 10:20:30 vixie Exp $";
  4. #endif /* not lint */
  5.  
  6. /*
  7.  * ++Copyright++ 1986
  8.  * -
  9.  * Copyright (c) 1986
  10.  *    The Regents of the University of California.  All rights reserved.
  11.  * 
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *     This product includes software developed by the University of
  23.  *     California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  * -
  40.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  41.  * 
  42.  * Permission to use, copy, modify, and distribute this software for any
  43.  * purpose with or without fee is hereby granted, provided that the above
  44.  * copyright notice and this permission notice appear in all copies, and that
  45.  * the name of Digital Equipment Corporation not be used in advertising or
  46.  * publicity pertaining to distribution of the document or software without
  47.  * specific, written prior permission.
  48.  * 
  49.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  50.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  51.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  52.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  53.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  54.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  55.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56.  * SOFTWARE.
  57.  * -
  58.  * --Copyright--
  59.  */
  60.  
  61. #include <sys/param.h>
  62. #include <sys/socket.h>
  63. #include <netinet/in.h>
  64. #include <arpa/inet.h>
  65. #include <arpa/nameser.h>
  66.  
  67. #include <syslog.h>
  68. #include <resolv.h>
  69. #include <stdio.h>
  70. #include <errno.h>
  71.  
  72. #include "named.h"
  73.  
  74. /*
  75.  * Forward the query to get the answer since its not in the database.
  76.  * Returns FW_OK if a request struct is allocated and the query sent.
  77.  * Returns FW_DUP if this is a duplicate of a pending request. 
  78.  * Returns FW_NOSERVER if there were no addresses for the nameservers.
  79.  * Returns FW_SERVFAIL on malloc error or if asked to do something
  80.  * dangerous, such as fwd to ourselves or fwd to the host that asked us.
  81.  *
  82.  * (no action is taken on errors and qpp is not filled in.)
  83.  */
  84. int
  85. ns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname, np)
  86.     struct databuf *nsp[];
  87.     u_char *msg;
  88.     int msglen;
  89.     struct sockaddr_in *fp;
  90.     struct qstream *qsp;
  91.     int dfd;
  92.     struct qinfo **qpp;
  93.     char *dname;
  94.     struct namebuf *np;
  95. {
  96.     register struct qinfo *qp;
  97.     struct sockaddr_in *nsa;
  98.     HEADER *hp;
  99.     u_int16_t id;
  100.     int n;
  101.  
  102.     dprintf(3, (ddt, "ns_forw()\n"));
  103.  
  104.     hp = (HEADER *) msg;
  105.     id = hp->id;
  106.     /* Look at them all */
  107.     for (qp = nsqhead; qp != QINFO_NULL; qp = qp->q_link) {
  108.         if (qp->q_id == id &&
  109.             bcmp((char *)&qp->q_from, fp, sizeof(qp->q_from)) == 0 &&
  110.             ((qp->q_cmsglen == 0 && qp->q_msglen == msglen &&
  111.              bcmp((char *)qp->q_msg+2, msg+2, msglen-2) == 0) ||
  112.             (qp->q_cmsglen == msglen &&
  113.              bcmp((char *)qp->q_cmsg+2, msg+2, msglen-2) == 0))) {
  114.             dprintf(3, (ddt,
  115.                     "forw: dropped DUP id=%d\n", ntohs(id)));
  116.             nameserIncr(fp->sin_addr, nssRcvdDupQ);
  117.             return (FW_DUP);
  118.         }
  119.     }
  120.  
  121.     qp = qnew();
  122. #if defined(LAME_DELEGATION) || defined(VALIDATE)
  123.     getname(np, qp->q_domain, sizeof qp->q_domain);
  124. #endif
  125.     qp->q_from = *fp;    /* nslookup wants to know this */
  126.     if ((n = nslookup(nsp, qp, dname, "ns_forw")) < 0) {
  127.         dprintf(2, (ddt, "forw: nslookup reports danger\n"));
  128.         qfree(qp);
  129.         return (FW_SERVFAIL);
  130.     } else if (n == 0 && !fwdtab) {
  131.         dprintf(2, (ddt, "forw: no nameservers found\n"));
  132.         qfree(qp);
  133.         return (FW_NOSERVER);
  134.     }
  135.     qp->q_stream = qsp;
  136.     qp->q_curaddr = 0;
  137.     qp->q_fwd = fwdtab;
  138.     qp->q_dfd = dfd;
  139.     qp->q_id = id;
  140.     qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
  141.     hp->id = qp->q_nsid = htons(nsid_next());
  142.     hp->ancount = htons(0);
  143.     hp->nscount = htons(0);
  144.     hp->arcount = htons(0);
  145.     if ((qp->q_msg = (u_char *)malloc((unsigned)msglen)) == NULL) {
  146.         syslog(LOG_NOTICE, "forw: malloc: %m");
  147.         qfree(qp);
  148.         return (FW_SERVFAIL);
  149.     }
  150.     bcopy(msg, qp->q_msg, qp->q_msglen = msglen);
  151.     if (!qp->q_fwd) {
  152.         hp->rd = 0;
  153.         qp->q_addr[0].stime = tt;
  154.     }
  155.  
  156. #ifdef SLAVE_FORWARD
  157.     if (forward_only)
  158.         schedretry(qp, (time_t)slave_retry);
  159.     else
  160. #endif /* SLAVE_FORWARD */
  161.     schedretry(qp, qp->q_fwd ?(2*RETRYBASE) :retrytime(qp));
  162.  
  163.     nsa = Q_NEXTADDR(qp, 0);
  164.     dprintf(1, (ddt,
  165.         "forw: forw -> [%s].%d ds=%d nsid=%d id=%d %dms retry %dsec\n",
  166.             inet_ntoa(nsa->sin_addr),
  167.             ntohs(nsa->sin_port), ds,
  168.             ntohs(qp->q_nsid), ntohs(qp->q_id),
  169.             (qp->q_addr[0].nsdata != NULL)
  170.                 ? qp->q_addr[0].nsdata->d_nstime
  171.                 : -1,
  172.             (int)(qp->q_time - tt.tv_sec)));
  173. #ifdef DEBUG
  174.     if (debug >= 10)
  175.         fp_nquery(msg, msglen, ddt);
  176. #endif
  177.     if (sendto(ds, (char *)msg, msglen, 0, (struct sockaddr *)nsa,
  178.            sizeof(struct sockaddr_in)) < 0) {
  179.         if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
  180.             syslog(LOG_INFO, "ns_forw: sendto([%s].%d): %m",
  181.                    inet_ntoa(nsa->sin_addr), ntohs(nsa->sin_port));
  182.         nameserIncr(nsa->sin_addr, nssSendtoErr);
  183.     }
  184.     nameserIncr(fp->sin_addr, nssRcvdFwdQ);
  185.     nameserIncr(nsa->sin_addr, nssSentFwdQ);
  186.     if (qpp)
  187.         *qpp = qp;
  188.     hp->rd = 1;
  189.     return (0);
  190. }
  191.  
  192. /* struct qdatagram *
  193.  * aIsUs(addr)
  194.  *    scan the datagramq (our list of interface addresses) for "addr"
  195.  * returns:
  196.  *    pointer to qdatagram entry or NULL if no match is found
  197.  * notes:
  198.  *    INADDR_ANY ([0.0.0.0]) is on the datagramq, so it's considered "us"
  199.  * author:
  200.  *    Paul Vixie (DECWRL) April 1991
  201.  */
  202. struct qdatagram *
  203. aIsUs(addr)
  204.     struct in_addr addr;
  205. {
  206.     struct qdatagram *dqp;
  207.  
  208.     for (dqp = datagramq;  dqp != QDATAGRAM_NULL;  dqp = dqp->dq_next) {
  209.         if (addr.s_addr == dqp->dq_addr.s_addr) {
  210.             return dqp;
  211.         }
  212.     }
  213.     return NULL;
  214. }
  215.  
  216. /* haveComplained(tag1, tag2)
  217.  *    check to see if we have complained about (tag1,tag2) recently
  218.  *    (note that these are declared as pointers but are never deref'd)
  219.  * returns:
  220.  *    boolean: have we complained recently?
  221.  * side-effects:
  222.  *    outdated complaint records removed from our static list
  223.  * author:
  224.  *    Paul Vixie (DECWRL) April 1991
  225.  */
  226. int
  227. haveComplained(tag1, tag2)
  228.     const char *tag1, *tag2;
  229. {
  230.     struct complaint {
  231.         const char *tag1, *tag2;
  232.         time_t expire;
  233.         struct complaint *next;
  234.     };
  235.     static struct complaint *List = NULL;
  236.     struct complaint *cur, *next, *prev;
  237.     int r = 0;
  238.  
  239.     for (cur = List, prev = NULL;  cur;  prev = cur, cur = next) {
  240.         next = cur->next;
  241.         if (tt.tv_sec > cur->expire) {
  242.             if (prev)
  243.                 prev->next = next;
  244.             else
  245.                 List = next;
  246.             free((char*) cur);
  247.             cur = prev;
  248.         } else if ((tag1 == cur->tag1) && (tag2 == cur->tag2)) {
  249.             r++;
  250.         }
  251.     }
  252.     if (!r) {
  253.         cur = (struct complaint *)malloc(sizeof(stru